//
// Test Suite for geos::geom::Envelope class.

// tut
#include <tut/tut.hpp>
// geos
#include <geos/geom/Envelope.h>
#include <geos/geom/Coordinate.h>

namespace tut {
//
// Test Group
//

// dummy data, not used
struct test_envelope_data {};

typedef test_group<test_envelope_data> group;
typedef group::object object;

group test_envelope_group("geos::geom::Envelope");

//
// Test Cases
//

// 1 - Test of default constructor
template<>
template<>
void object::test<1>
()
{
    geos::geom::Envelope empty;

    ensure(empty.isNull());

    ensure_equals(empty.getWidth(), 0);
    ensure_equals(empty.getHeight(), 0);
}

// 2 - Test of overriden constructor
template<>
template<>
void object::test<2>
()
{
    geos::geom::Envelope box(0, 100, 0, 100);

    ensure(!box.isNull());

    ensure_equals(box.getMinX(), 0);
    ensure_equals(box.getMaxX(), 100);
    ensure_equals(box.getMinY(), 0);
    ensure_equals(box.getMaxY(), 100);

    ensure_equals(box.getMinX(), box.getMinY());
    ensure_equals(box.getMaxX(), box.getMaxY());

    ensure_equals(box.getWidth(), box.getHeight());
}

// 3 - Test of copy constructor
template<>
template<>
void object::test<3>
()
{
    geos::geom::Envelope box(0, 100, 0, 100);

    ensure(!box.isNull());
    ensure_equals(box.getWidth(), box.getHeight());

    geos::geom::Envelope copied(box);

    ensure(!copied.isNull());
    ensure(copied == box);
    ensure_equals(copied.getWidth(), copied.getHeight());
}

// 4 - Test of setToNull()
template<>
template<>
void object::test<4>
()
{
    geos::geom::Envelope e(100, 200, 100, 200);

    ensure(!e.isNull());
    e.setToNull();
    ensure(e.isNull());
}

// 5 - Test of equals()
template<>
template<>
void object::test<5>
()
{
    geos::geom::Envelope empty;
    geos::geom::Envelope zero(0, 0, 0, 0);
    geos::geom::Envelope zero2(0, 0, 0, 0);
    geos::geom::Envelope box(0, 100, 0, 100);

    ensure(empty.isNull());
    ensure(!zero.isNull());
    ensure(!zero2.isNull());
    ensure(!box.isNull());

    /* See http://trac.osgeo.org/geos/ticket/703 */
    ensure(empty.equals(&empty));

    ensure(!empty.equals(&zero));
    ensure(!zero.equals(&empty));

    ensure(zero.equals(&zero2));
    ensure(zero2.equals(&zero));

    ensure(!box.equals(&empty));
    ensure(!box.equals(&zero));
}

// 6 - Test of contains()
template<>
template<>
void object::test<6>
()
{
    geos::geom::Envelope empty;
    geos::geom::Envelope small(-1, 1, -1, 1);
    geos::geom::Envelope big(-5, 5, -5, 5);

    ensure(empty.isNull());
    ensure(!small.isNull());
    ensure(!big.isNull());

    // Test empty envelope by reference
    ensure("empty envelope is not empty!", !empty.contains(small));
    ensure("empty envelope is not empty!", !small.contains(empty));

    // Test empty envelope by pointer
    ensure("empty envelope is not empty!", !empty.contains(&small));
    ensure("empty envelope is not empty!", !small.contains(&empty));

    // Test non-empty envelope by reference
    ensure(!small.contains(big));
    ensure(big.contains(small));

    // Test raw point
    ensure(small.contains(0, 0));
    ensure(small.contains(-1, -1));
    ensure(!small.contains(5, 5));

    // Test coordinate
    geos::geom::Coordinate origin(0, 0, 0);

    ensure_equals(origin.x, 0);
    ensure_equals(origin.y, 0);
    ensure_equals(origin.z, 0);
    ensure(small.contains(origin));
}

// Test of intersects()
template<>
template<>
void object::test<7>
()
{
    geos::geom::Envelope empty;
    geos::geom::Envelope with_origin(-100, 100, -100, 100);
    geos::geom::Envelope moved(50, 150, 50, 150);

    ensure(empty.isNull());
    ensure(!with_origin.isNull());
    ensure(!moved.isNull());

    // Test empty envelope by reference
    ensure("empty envelope seems not empty!", !empty.intersects(with_origin));
    ensure("empty envelope seems not empty!", !with_origin.intersects(empty));

    // Test empty envelope by pointer
    ensure("empty envelope seems not empty!", !empty.intersects(&with_origin));
    ensure("empty envelope seems not empty!", !with_origin.intersects(&empty));

    // Test non-empty envelope by reference
    ensure(with_origin.intersects(moved));
    ensure(moved.intersects(with_origin));

    // Test intersection with raw point
    ensure(with_origin.intersects(0, 0));
    ensure(with_origin.intersects(-100, 100));
    ensure(!with_origin.intersects(-200, 200));

    // Test intersection with coordinate
    geos::geom::Coordinate origin(0, 0, 0);

    ensure_equals(origin.x, 0);
    ensure_equals(origin.y, 0);
    ensure_equals(origin.z, 0);
    ensure(with_origin.intersects(origin));

}

// Test of expand()
template<>
template<>
void object::test<8>
()
{
    geos::geom::Envelope empty;
    geos::geom::Envelope box(-5, 5, -5, 5); // Includes (0,0) point
    const geos::geom::Envelope exemplar(-5, 5, -5, 5);

    ensure(empty.isNull());
    ensure(!box.isNull());
    ensure(!exemplar.isNull());

    // Expand box envelope to include null envelope
    box.expandToInclude(&empty);
    ensure(box == exemplar);   // no change expected

    // Expand null envelope to include box envelope
    empty.expandToInclude(&box);
    ensure(empty == exemplar);
}

// Second test of expand()
template<>
template<>
void object::test<9>
()
{
    geos::geom::Envelope empty;
    geos::geom::Envelope box(100, 101, 100, 101); // Does not include (0,0) point
    const geos::geom::Envelope exemplar(100, 101, 100, 101);

    // Expand box envelope to include null envelope
    box.expandToInclude(&empty);
    ensure(box == exemplar);   // no change expected

    // Expand empty envelope to include bigger envelope
    empty.expandToInclude(&box);
    ensure(empty == exemplar);
}

} // namespace tut

